package switchviz.network.netswitch;

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseEvent;
import java.io.IOException;

import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.event.TreeSelectionEvent;

import org.apache.log4j.Logger;

import switchviz.Application;
import switchviz.core.ResourceManager;
import switchviz.gui.component.IListener;
import switchviz.gui.component.PopupMenu;
import switchviz.gui.component.TestNetworkOptionPane;
import switchviz.gui.component.XMLTreeNode;
import switchviz.network.NetworkException;
import switchviz.network.NetworkFacade;

public class SwitchPanel extends JPanel implements IListener, ComponentListener
{
	private static Logger logger = Logger.getLogger(SwitchPanel.class);
	private static final long serialVersionUID = -2487671548788323753L;
	private SwitchTree _switchtree = null;
	private SwitchConfigurationPanel _configpanel = null;
	private SwitchDataModel _datamodel = null;
	private PopupMenu _popup = null;
	private boolean _getportinfo = false;

	public SwitchPanel()
	{
		if (logger.isInfoEnabled()) { logger.info("Initialize ..."); }
		this.initialize();
	}
	
	private void initialize()
	{
		this.setLayout(ResourceManager.getInstance().getBorderLayout());
		this.add(getConfigurationPanel(), BorderLayout.CENTER);
		this.add(getSwitchTree(), BorderLayout.WEST);
		this.addComponentListener(this);
	}
	
	private SwitchConfigurationPanel getConfigurationPanel()
	{
		if (_configpanel == null)
		{
			_configpanel = new SwitchConfigurationPanel();
			_configpanel.addListener(this);
		}
		return _configpanel;
	}
	
	private SwitchTree getSwitchTree()
	{
		if (_switchtree == null)
		{
			try 
			{
				_switchtree = new SwitchTree(ResourceManager.getInstance().getSwitchConfigurationFile(), new SwitchXMLFilter());
				_switchtree.getTree().addTreeSelectionListener(this);
				_switchtree.getTree().addMouseListener(this);
				_popup = new PopupMenu(new String[]{ResourceManager.getInstance().getActionAddSwitch(), ResourceManager.getInstance().getActionRemoveSwitch(), ResourceManager.getInstance().getActionRefresh()}, this);
			} 
			catch (Exception e) { logger.error(e.getMessage()); }
		}
		return _switchtree;
	}
	
	private SwitchDataModel getSwitchModel()
	{
		if (_datamodel == null)
			_datamodel = new SwitchDataModel();
		
		return _datamodel;
	}
	
	
	public void actionPerformed(ActionEvent evt)
	{
		String command = evt.getActionCommand();

		try
		{
		    if (ResourceManager.getInstance().getActionAddSwitch().equals(command))
		    {
		    	if(logger.isInfoEnabled())
					logger.info("Create a new Switch.");
		    	getSwitchTree().addSwitchNode("new switch");
		    	getSwitchTree().saveXML();
		    }
		    else if (ResourceManager.getInstance().getActionRemoveSwitch().equals(command))
		    {
		    	getSwitchTree().removeNode();
		    	getSwitchTree().saveXML();
		    }
		    else if(ResourceManager.getInstance().getActionRefresh().equals(command))
	        {
		    	getSwitchTree().reload();
		    	getSwitchTree().getTree().setSelectionRow(0);
	        }
		    else if (ResourceManager.getInstance().getActionApply().equals(command))
		    {
	        	if (((XMLTreeNode)getSwitchTree().getTree().getLastSelectedPathComponent()).isRoot()) { return; }
	        	_getportinfo = false;
	        	new ApplyWorkerThread().execute();
		    }
		    else if (ResourceManager.getInstance().getActionTest().equals(command))
		    {
		    	_datamodel = getConfigurationPanel().getValues();
		    	new TestNetworkOptionPane(Application.getInstance().getMainFrame(), getSwitchModel());
		    }
		    else if (ResourceManager.getInstance().getActionGetData().equals(command))
		    {
		    	_getportinfo = true;
		    	new ApplyWorkerThread().execute();
		    }

		}
		catch (Exception e1) 
		{ 
			logger.error(e1.getMessage()); 
		}
	}
	
	private void saveConfiguration() throws NetworkException, IOException
	{
    	_datamodel = getConfigurationPanel().getValues();
    	if (_datamodel.getName().trim().equals(""))
		{
			JOptionPane.showMessageDialog(this,
				    "Please insert a name",
				    "Form not complete!",
				    JOptionPane.WARNING_MESSAGE);
			return;
		}
    	if(_getportinfo)
    	{
			Cursor cursor = this.getCursor();
			this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
			getConfigurationPanel().enableApplyButton(false);
			getConfigurationPanel().firstConnectInitialize();
			
			if(logger.isInfoEnabled())
				logger.info("Getting Port and Type Information from the Switch.");
    		_datamodel.setPortList(NetworkFacade.getNumberOfPorts(_datamodel));
    		_datamodel.setType(NetworkFacade.getSwitchType(_datamodel));
    		
    		this.setCursor(cursor);
    		getConfigurationPanel().enableApplyButton(true);
    		getConfigurationPanel().setValues(_datamodel);
    	}
    	getSwitchTree().changeCurrentNode(_datamodel);
    	getSwitchTree().saveXML();
    	getConfigurationPanel().testEnableButtons();
	}

	public void valueChanged(TreeSelectionEvent evt) 
	{
		XMLTreeNode currentnode = (XMLTreeNode)evt.getPath().getLastPathComponent();
		if (currentnode.isRoot()) 
		{ 
			getSwitchModel().setName("");
			getSwitchModel().setAddress("");
			getSwitchModel().setPort(0);
			getSwitchModel().setDescription("");
			getSwitchModel().setCommunity("");
			getSwitchModel().setTimeout(0);
			getSwitchModel().setMaxRetries(0);
			getSwitchModel().setPDUCapacity(0);
			getConfigurationPanel().setValues(getSwitchModel());
			return; 
		}
		
		if (!SwitchTree.SWITCHNODE.equals(currentnode.getElement().getName()))
			currentnode = (XMLTreeNode)currentnode.getParent();
		
		
//		getSwitchModel().setName(currentnode.getElement().getChildTextNormalize(SwitchTree.SWITCHNAME));
//		getSwitchModel().setAddress(currentnode.getElement().getChildTextNormalize(SwitchTree.SWITCHADDRESS));
//		getSwitchModel().setPort(Integer.valueOf(currentnode.getElement().getChildTextNormalize(SwitchTree.SWITCHPORT)));
//		getSwitchModel().setDescription(currentnode.getElement().getChildTextNormalize(SwitchTree.SWITCHDESCRIPTION));
//		getSwitchModel().setCommunity(currentnode.getElement().getChildTextNormalize(SwitchTree.SWITCHCOMMUNITY));
//		getSwitchModel().setTimeout(Long.valueOf(currentnode.getElement().getChildTextNormalize(SwitchTree.SWITCHTIMEOUT)));
//		getSwitchModel().setMaxRetries(Integer.valueOf(currentnode.getElement().getChildTextNormalize(SwitchTree.SWITCHMAXRETRIES)));
//		getSwitchModel().setPDUCapacity(Integer.valueOf(currentnode.getElement().getChildTextNormalize(SwitchTree.SWITCHPDUCAPACITY)));
		
		getConfigurationPanel().setValues(SwitchTree.createSwitchModel(currentnode.getElement()));
		getConfigurationPanel().testEnableButtons();
		
	}

	public void mousePressed(MouseEvent e) 
	{
		if (e.isPopupTrigger() || e.getButton() == 3) 
            _popup.show(e.getComponent(), e.getX(), e.getY());
	}
	
	public void componentShown(ComponentEvent evt) 
	{
		try
		{
			getSwitchTree().reload();
		}
		catch(Exception e)
		{
			logger.error(e.getMessage());
			e.printStackTrace();
		}
	}
	
	public void componentHidden(ComponentEvent arg0) {}
	public void componentMoved(ComponentEvent arg0) {}
	public void componentResized(ComponentEvent arg0) {}
	
	public void mouseClicked(MouseEvent arg0) {}
	public void mouseEntered(MouseEvent arg0) {}
	public void mouseExited(MouseEvent arg0) {}
	public void mouseReleased(MouseEvent arg0) {}
	
	class ApplyWorkerThread extends SwingWorker<Void, Void>
	{
		public Void doInBackground() throws Exception 
		{
			saveConfiguration();
			return null;
		}
		
		public void done()
		{
			try 
			{
				get();
			} 
			catch (Exception e) 
			{
				e.printStackTrace();
				logger.error(e.getMessage());
			}
		}
	}
}
